/***************************************************************************
 *   Copyright (C) 2008 by Dominik Seichter                                *
 *   domseichter@web.de                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "PdfDifferenceEncoding.h"

#include "base/PdfDefinesPrivate.h"

#include "base/PdfArray.h"
#include "base/PdfDictionary.h"

#include "PdfFont.h"

#include <cstdlib>
#include <cstring>
#include <sstream>
#include <algorithm>

namespace PoDoFo {

static struct {
    pdf_utf16be u; // in fact this might be little endian on LE systems
    const char *name;
} nameToUnicodeTab[] = {
  {0x0021, "!"},
  {0x0023, "#"},
  {0x0024, "$"},
  {0x0025, "%"},
  {0x0026, "&"},
  {0x0027, "'"},
  {0x0028, "("},
  {0x0029, ")"},
  {0x002a, "*"},
  {0x002b, "+"},
  {0x002c, ","},
  {0x002d, "-"},
  {0x002e, "."},
  {0x002f, "/"},
  {0x0030, "0"},
  {0x0031, "1"},
  {0x0032, "2"},
  {0x0033, "3"},
  {0x0034, "4"},
  {0x0035, "5"},
  {0x0036, "6"},
  {0x0037, "7"},
  {0x0038, "8"},
  {0x0039, "9"},
  {0x003a, ":"},
  {0x003b, ";"},
  {0x003c, "<"},
  {0x003d, "="},
  {0x003e, ">"},
  {0x003f, "?"},
  {0x0040, "@"},
  {0x0041, "A"},
  {0x00c6, "AE"},
  {0x01fc, "AEacute"},
  {0x00c6, "AEsmall"},
  {0x00c1, "Aacute"},
  {0x00c1, "Aacutesmall"},
  {0x0102, "Abreve"},
  {0x00c2, "Acircumflex"},
  {0x00c2, "Acircumflexsmall"},
  {0xf6c9, "Acute"},
  {0xf6c9, "Acutesmall"},
  {0x00c4, "Adieresis"},
  {0x00c4, "Adieresissmall"},
  {0x00c0, "Agrave"},
  {0x00c0, "Agravesmall"},
  {0x0391, "Alpha"},
  {0x0386, "Alphatonos"},
  {0x0100, "Amacron"},
  {0x0104, "Aogonek"},
  {0x00c5, "Aring"},
  {0x01fa, "Aringacute"},
  {0x00c5, "Aringsmall"},
  {0x0041, "Asmall"},
  {0x00c3, "Atilde"},
  {0x00c3, "Atildesmall"},
  {0x0042, "B"},
  {0x0392, "Beta"},
  {0xf6f4, "Brevesmall"},
  {0x0042, "Bsmall"},
  {0x0043, "C"},
  {0x0106, "Cacute"},
  {0xf6ca, "Caron"},
  {0xf6ca, "Caronsmall"},
  {0x010c, "Ccaron"},
  {0x00c7, "Ccedilla"},
  {0x00c7, "Ccedillasmall"},
  {0x0108, "Ccircumflex"},
  {0x010a, "Cdotaccent"},
  {0xf7b8, "Cedillasmall"},
  {0x03a7, "Chi"},
  {0xf6f6, "Circumflexsmall"},
  {0x0043, "Csmall"},
  {0x0044, "D"},
  {0x010e, "Dcaron"},
  {0x0110, "Dcroat"},
  {0x2206, "Delta"},
  {0xf6cb, "Dieresis"},
  {0xf6cc, "DieresisAcute"},
  {0xf6cd, "DieresisGrave"},
  {0xf6cb, "Dieresissmall"},
  {0xf6f7, "Dotaccentsmall"},
  {0x0044, "Dsmall"},
  {0x0045, "E"},
  {0x00c9, "Eacute"},
  {0x00c9, "Eacutesmall"},
  {0x0114, "Ebreve"},
  {0x011a, "Ecaron"},
  {0x00ca, "Ecircumflex"},
  {0x00ca, "Ecircumflexsmall"},
  {0x00cb, "Edieresis"},
  {0x00cb, "Edieresissmall"},
  {0x0116, "Edotaccent"},
  {0x00c8, "Egrave"},
  {0x00c8, "Egravesmall"},
  {0x0112, "Emacron"},
  {0x014a, "Eng"},
  {0x0118, "Eogonek"},
  {0x0395, "Epsilon"},
  {0x0388, "Epsilontonos"},
  {0x0045, "Esmall"},
  {0x0397, "Eta"},
  {0x0389, "Etatonos"},
  {0x00d0, "Eth"},
  {0x00d0, "Ethsmall"},
  {0x20ac, "Euro"},
  {0x0046, "F"},
  {0x0046, "Fsmall"},
  {0x0047, "G"},
  {0x0393, "Gamma"},
  {0x011e, "Gbreve"},
  {0x01e6, "Gcaron"},
  {0x011c, "Gcircumflex"},
  {0x0122, "Gcommaaccent"},
  {0x0120, "Gdotaccent"},
  {0xf6ce, "Grave"},
  {0xf6ce, "Gravesmall"},
  {0x0047, "Gsmall"},
  {0x0048, "H"},
  {0x25cf, "H18533"},
  {0x25aa, "H18543"},
  {0x25ab, "H18551"},
  {0x25a1, "H22073"},
  {0x0126, "Hbar"},
  {0x0124, "Hcircumflex"},
  {0x0048, "Hsmall"},
  {0xf6cf, "Hungarumlaut"},
  {0xf6cf, "Hungarumlautsmall"},
  {0x0049, "I"},
  {0x0132, "IJ"},
  {0x00cd, "Iacute"},
  {0x00cd, "Iacutesmall"},
  {0x012c, "Ibreve"},
  {0x00ce, "Icircumflex"},
  {0x00ce, "Icircumflexsmall"},
  {0x00cf, "Idieresis"},
  {0x00cf, "Idieresissmall"},
  {0x0130, "Idotaccent"},
  {0x2111, "Ifraktur"},
  {0x00cc, "Igrave"},
  {0x00cc, "Igravesmall"},
  {0x012a, "Imacron"},
  {0x012e, "Iogonek"},
  {0x0399, "Iota"},
  {0x03aa, "Iotadieresis"},
  {0x038a, "Iotatonos"},
  {0x0049, "Ismall"},
  {0x0128, "Itilde"},
  {0x004a, "J"},
  {0x0134, "Jcircumflex"},
  {0x004a, "Jsmall"},
  {0x004b, "K"},
  {0x039a, "Kappa"},
  {0x0136, "Kcommaaccent"},
  {0x004b, "Ksmall"},
  {0x004c, "L"},
  {0xf6bf, "LL"},
  {0x0139, "Lacute"},
  {0x039b, "Lambda"},
  {0x013d, "Lcaron"},
  {0x013b, "Lcommaaccent"},
  {0x013f, "Ldot"},
  {0x0141, "Lslash"},
  {0x0141, "Lslashsmall"},
  {0x004c, "Lsmall"},
  {0x004d, "M"},
  {0xf6d0, "Macron"},
  {0xf6d0, "Macronsmall"},
  {0x004d, "Msmall"},
  {0x039c, "Mu"},
  {0x004e, "N"},
  {0x0143, "Nacute"},
  {0x0147, "Ncaron"},
  {0x0145, "Ncommaaccent"},
  {0x004e, "Nsmall"},
  {0x00d1, "Ntilde"},
  {0x00d1, "Ntildesmall"},
  {0x039d, "Nu"},
  {0x004f, "O"},
  {0x0152, "OE"},
  {0x0152, "OEsmall"},
  {0x00d3, "Oacute"},
  {0x00d3, "Oacutesmall"},
  {0x014e, "Obreve"},
  {0x00d4, "Ocircumflex"},
  {0x00d4, "Ocircumflexsmall"},
  {0x00d6, "Odieresis"},
  {0x00d6, "Odieresissmall"},
  {0xf6fb, "Ogoneksmall"},
  {0x00d2, "Ograve"},
  {0x00d2, "Ogravesmall"},
  {0x01a0, "Ohorn"},
  {0x0150, "Ohungarumlaut"},
  {0x014c, "Omacron"},
  {0x2126, "Omega"},
  {0x038f, "Omegatonos"},
  {0x039f, "Omicron"},
  {0x038c, "Omicrontonos"},
  {0x00d8, "Oslash"},
  {0x01fe, "Oslashacute"},
  {0x00d8, "Oslashsmall"},
  {0x004f, "Osmall"},
  {0x00d5, "Otilde"},
  {0x00d5, "Otildesmall"},
  {0x0050, "P"},
  {0x03a6, "Phi"},
  {0x03a0, "Pi"},
  {0x03a8, "Psi"},
  {0x0050, "Psmall"},
  {0x0051, "Q"},
  {0x0051, "Qsmall"},
  {0x0052, "R"},
  {0x0154, "Racute"},
  {0x0158, "Rcaron"},
  {0x0156, "Rcommaaccent"},
  {0x211c, "Rfraktur"},
  {0x03a1, "Rho"},
  {0xf6fc, "Ringsmall"},
  {0x0052, "Rsmall"},
  {0x0053, "S"},
  {0x250c, "SF010000"},
  {0x2514, "SF020000"},
  {0x2510, "SF030000"},
  {0x2518, "SF040000"},
  {0x253c, "SF050000"},
  {0x252c, "SF060000"},
  {0x2534, "SF070000"},
  {0x251c, "SF080000"},
  {0x2524, "SF090000"},
  {0x2500, "SF100000"},
  {0x2502, "SF110000"},
  {0x2561, "SF190000"},
  {0x2562, "SF200000"},
  {0x2556, "SF210000"},
  {0x2555, "SF220000"},
  {0x2563, "SF230000"},
  {0x2551, "SF240000"},
  {0x2557, "SF250000"},
  {0x255d, "SF260000"},
  {0x255c, "SF270000"},
  {0x255b, "SF280000"},
  {0x255e, "SF360000"},
  {0x255f, "SF370000"},
  {0x255a, "SF380000"},
  {0x2554, "SF390000"},
  {0x2569, "SF400000"},
  {0x2566, "SF410000"},
  {0x2560, "SF420000"},
  {0x2550, "SF430000"},
  {0x256c, "SF440000"},
  {0x2567, "SF450000"},
  {0x2568, "SF460000"},
  {0x2564, "SF470000"},
  {0x2565, "SF480000"},
  {0x2559, "SF490000"},
  {0x2558, "SF500000"},
  {0x2552, "SF510000"},
  {0x2553, "SF520000"},
  {0x256b, "SF530000"},
  {0x256a, "SF540000"},
  {0x015a, "Sacute"},
  {0x0160, "Scaron"},
  {0x0160, "Scaronsmall"},
  {0x015e, "Scedilla"},
  {0x015c, "Scircumflex"},
  {0x0218, "Scommaaccent"},
  {0x03a3, "Sigma"},
  {0x0053, "Ssmall"},
  {0x0054, "T"},
  {0x03a4, "Tau"},
  {0x0166, "Tbar"},
  {0x0164, "Tcaron"},
  {0x0162, "Tcommaaccent"},
  {0x0398, "Theta"},
  {0x00de, "Thorn"},
  {0x00de, "Thornsmall"},
  {0xf6fe, "Tildesmall"},
  {0x0054, "Tsmall"},
  {0x0055, "U"},
  {0x00da, "Uacute"},
  {0x00da, "Uacutesmall"},
  {0x016c, "Ubreve"},
  {0x00db, "Ucircumflex"},
  {0x00db, "Ucircumflexsmall"},
  {0x00dc, "Udieresis"},
  {0x00dc, "Udieresissmall"},
  {0x00d9, "Ugrave"},
  {0x00d9, "Ugravesmall"},
  {0x01af, "Uhorn"},
  {0x0170, "Uhungarumlaut"},
  {0x016a, "Umacron"},
  {0x0172, "Uogonek"},
  {0x03a5, "Upsilon"},
  {0x03d2, "Upsilon1"},
  {0x03ab, "Upsilondieresis"},
  {0x038e, "Upsilontonos"},
  {0x016e, "Uring"},
  {0x0055, "Usmall"},
  {0x0168, "Utilde"},
  {0x0056, "V"},
  {0x0056, "Vsmall"},
  {0x0057, "W"},
  {0x1e82, "Wacute"},
  {0x0174, "Wcircumflex"},
  {0x1e84, "Wdieresis"},
  {0x1e80, "Wgrave"},
  {0x0057, "Wsmall"},
  {0x0058, "X"},
  {0x039e, "Xi"},
  {0x0058, "Xsmall"},
  {0x0059, "Y"},
  {0x00dd, "Yacute"},
  {0x00dd, "Yacutesmall"},
  {0x0176, "Ycircumflex"},
  {0x0178, "Ydieresis"},
  {0x0178, "Ydieresissmall"},
  {0x1ef2, "Ygrave"},
  {0x0059, "Ysmall"},
  {0x005a, "Z"},
  {0x0179, "Zacute"},
  {0x017d, "Zcaron"},
  {0x017d, "Zcaronsmall"},
  {0x017b, "Zdotaccent"},
  {0x0396, "Zeta"},
  {0x005a, "Zsmall"},
  {0x0022, "\""},
  {0x005c, "\\"},
  {0x005d, "]"},
  {0x005e, "^"},
  {0x005f, "_"},
  {0x0060, "`"},
  {0x0061, "a"},
  {0x00e1, "aacute"},
  {0x0103, "abreve"},
  {0x00e2, "acircumflex"},
  {0x00b4, "acute"},
  {0x0301, "acutecomb"},
  {0x00e4, "adieresis"},
  {0x00e6, "ae"},
  {0x01fd, "aeacute"},
  {0x2015, "afii00208"},
  {0x0410, "afii10017"},
  {0x0411, "afii10018"},
  {0x0412, "afii10019"},
  {0x0413, "afii10020"},
  {0x0414, "afii10021"},
  {0x0415, "afii10022"},
  {0x0401, "afii10023"},
  {0x0416, "afii10024"},
  {0x0417, "afii10025"},
  {0x0418, "afii10026"},
  {0x0419, "afii10027"},
  {0x041a, "afii10028"},
  {0x041b, "afii10029"},
  {0x041c, "afii10030"},
  {0x041d, "afii10031"},
  {0x041e, "afii10032"},
  {0x041f, "afii10033"},
  {0x0420, "afii10034"},
  {0x0421, "afii10035"},
  {0x0422, "afii10036"},
  {0x0423, "afii10037"},
  {0x0424, "afii10038"},
  {0x0425, "afii10039"},
  {0x0426, "afii10040"},
  {0x0427, "afii10041"},
  {0x0428, "afii10042"},
  {0x0429, "afii10043"},
  {0x042a, "afii10044"},
  {0x042b, "afii10045"},
  {0x042c, "afii10046"},
  {0x042d, "afii10047"},
  {0x042e, "afii10048"},
  {0x042f, "afii10049"},
  {0x0490, "afii10050"},
  {0x0402, "afii10051"},
  {0x0403, "afii10052"},
  {0x0404, "afii10053"},
  {0x0405, "afii10054"},
  {0x0406, "afii10055"},
  {0x0407, "afii10056"},
  {0x0408, "afii10057"},
  {0x0409, "afii10058"},
  {0x040a, "afii10059"},
  {0x040b, "afii10060"},
  {0x040c, "afii10061"},
  {0x040e, "afii10062"},
  {0xf6c4, "afii10063"},
  {0xf6c5, "afii10064"},
  {0x0430, "afii10065"},
  {0x0431, "afii10066"},
  {0x0432, "afii10067"},
  {0x0433, "afii10068"},
  {0x0434, "afii10069"},
  {0x0435, "afii10070"},
  {0x0451, "afii10071"},
  {0x0436, "afii10072"},
  {0x0437, "afii10073"},
  {0x0438, "afii10074"},
  {0x0439, "afii10075"},
  {0x043a, "afii10076"},
  {0x043b, "afii10077"},
  {0x043c, "afii10078"},
  {0x043d, "afii10079"},
  {0x043e, "afii10080"},
  {0x043f, "afii10081"},
  {0x0440, "afii10082"},
  {0x0441, "afii10083"},
  {0x0442, "afii10084"},
  {0x0443, "afii10085"},
  {0x0444, "afii10086"},
  {0x0445, "afii10087"},
  {0x0446, "afii10088"},
  {0x0447, "afii10089"},
  {0x0448, "afii10090"},
  {0x0449, "afii10091"},
  {0x044a, "afii10092"},
  {0x044b, "afii10093"},
  {0x044c, "afii10094"},
  {0x044d, "afii10095"},
  {0x044e, "afii10096"},
  {0x044f, "afii10097"},
  {0x0491, "afii10098"},
  {0x0452, "afii10099"},
  {0x0453, "afii10100"},
  {0x0454, "afii10101"},
  {0x0455, "afii10102"},
  {0x0456, "afii10103"},
  {0x0457, "afii10104"},
  {0x0458, "afii10105"},
  {0x0459, "afii10106"},
  {0x045a, "afii10107"},
  {0x045b, "afii10108"},
  {0x045c, "afii10109"},
  {0x045e, "afii10110"},
  {0x040f, "afii10145"},
  {0x0462, "afii10146"},
  {0x0472, "afii10147"},
  {0x0474, "afii10148"},
  {0xf6c6, "afii10192"},
  {0x045f, "afii10193"},
  {0x0463, "afii10194"},
  {0x0473, "afii10195"},
  {0x0475, "afii10196"},
  {0xf6c7, "afii10831"},
  {0xf6c8, "afii10832"},
  {0x04d9, "afii10846"},
  {0x200e, "afii299"},
  {0x200f, "afii300"},
  {0x200d, "afii301"},
  {0x066a, "afii57381"},
  {0x060c, "afii57388"},
  {0x0660, "afii57392"},
  {0x0661, "afii57393"},
  {0x0662, "afii57394"},
  {0x0663, "afii57395"},
  {0x0664, "afii57396"},
  {0x0665, "afii57397"},
  {0x0666, "afii57398"},
  {0x0667, "afii57399"},
  {0x0668, "afii57400"},
  {0x0669, "afii57401"},
  {0x061b, "afii57403"},
  {0x061f, "afii57407"},
  {0x0621, "afii57409"},
  {0x0622, "afii57410"},
  {0x0623, "afii57411"},
  {0x0624, "afii57412"},
  {0x0625, "afii57413"},
  {0x0626, "afii57414"},
  {0x0627, "afii57415"},
  {0x0628, "afii57416"},
  {0x0629, "afii57417"},
  {0x062a, "afii57418"},
  {0x062b, "afii57419"},
  {0x062c, "afii57420"},
  {0x062d, "afii57421"},
  {0x062e, "afii57422"},
  {0x062f, "afii57423"},
  {0x0630, "afii57424"},
  {0x0631, "afii57425"},
  {0x0632, "afii57426"},
  {0x0633, "afii57427"},
  {0x0634, "afii57428"},
  {0x0635, "afii57429"},
  {0x0636, "afii57430"},
  {0x0637, "afii57431"},
  {0x0638, "afii57432"},
  {0x0639, "afii57433"},
  {0x063a, "afii57434"},
  {0x0640, "afii57440"},
  {0x0641, "afii57441"},
  {0x0642, "afii57442"},
  {0x0643, "afii57443"},
  {0x0644, "afii57444"},
  {0x0645, "afii57445"},
  {0x0646, "afii57446"},
  {0x0648, "afii57448"},
  {0x0649, "afii57449"},
  {0x064a, "afii57450"},
  {0x064b, "afii57451"},
  {0x064c, "afii57452"},
  {0x064d, "afii57453"},
  {0x064e, "afii57454"},
  {0x064f, "afii57455"},
  {0x0650, "afii57456"},
  {0x0651, "afii57457"},
  {0x0652, "afii57458"},
  {0x0647, "afii57470"},
  {0x06a4, "afii57505"},
  {0x067e, "afii57506"},
  {0x0686, "afii57507"},
  {0x0698, "afii57508"},
  {0x06af, "afii57509"},
  {0x0679, "afii57511"},
  {0x0688, "afii57512"},
  {0x0691, "afii57513"},
  {0x06ba, "afii57514"},
  {0x06d2, "afii57519"},
  {0x06d5, "afii57534"},
  {0x20aa, "afii57636"},
  {0x05be, "afii57645"},
  {0x05c3, "afii57658"},
  {0x05d0, "afii57664"},
  {0x05d1, "afii57665"},
  {0x05d2, "afii57666"},
  {0x05d3, "afii57667"},
  {0x05d4, "afii57668"},
  {0x05d5, "afii57669"},
  {0x05d6, "afii57670"},
  {0x05d7, "afii57671"},
  {0x05d8, "afii57672"},
  {0x05d9, "afii57673"},
  {0x05da, "afii57674"},
  {0x05db, "afii57675"},
  {0x05dc, "afii57676"},
  {0x05dd, "afii57677"},
  {0x05de, "afii57678"},
  {0x05df, "afii57679"},
  {0x05e0, "afii57680"},
  {0x05e1, "afii57681"},
  {0x05e2, "afii57682"},
  {0x05e3, "afii57683"},
  {0x05e4, "afii57684"},
  {0x05e5, "afii57685"},
  {0x05e6, "afii57686"},
  {0x05e7, "afii57687"},
  {0x05e8, "afii57688"},
  {0x05e9, "afii57689"},
  {0x05ea, "afii57690"},
  {0xfb2a, "afii57694"},
  {0xfb2b, "afii57695"},
  {0xfb4b, "afii57700"},
  {0xfb1f, "afii57705"},
  {0x05f0, "afii57716"},
  {0x05f1, "afii57717"},
  {0x05f2, "afii57718"},
  {0xfb35, "afii57723"},
  {0x05b4, "afii57793"},
  {0x05b5, "afii57794"},
  {0x05b6, "afii57795"},
  {0x05bb, "afii57796"},
  {0x05b8, "afii57797"},
  {0x05b7, "afii57798"},
  {0x05b0, "afii57799"},
  {0x05b2, "afii57800"},
  {0x05b1, "afii57801"},
  {0x05b3, "afii57802"},
  {0x05c2, "afii57803"},
  {0x05c1, "afii57804"},
  {0x05b9, "afii57806"},
  {0x05bc, "afii57807"},
  {0x05bd, "afii57839"},
  {0x05bf, "afii57841"},
  {0x05c0, "afii57842"},
  {0x02bc, "afii57929"},
  {0x2105, "afii61248"},
  {0x2113, "afii61289"},
  {0x2116, "afii61352"},
  {0x202c, "afii61573"},
  {0x202d, "afii61574"},
  {0x202e, "afii61575"},
  {0x200c, "afii61664"},
  {0x066d, "afii63167"},
  {0x02bd, "afii64937"},
  {0x00e0, "agrave"},
  {0x2135, "aleph"},
  {0x03b1, "alpha"},
  {0x03ac, "alphatonos"},
  {0x0101, "amacron"},
  {0x0026, "ampersand"},
  {0x0026, "ampersandsmall"},
  {0x2220, "angle"},
  {0x2329, "angleleft"},
  {0x232a, "angleright"},
  {0x0387, "anoteleia"},
  {0x0105, "aogonek"},
  {0x2248, "approxequal"},
  {0x00e5, "aring"},
  {0x01fb, "aringacute"},
  {0x2194, "arrowboth"},
  {0x21d4, "arrowdblboth"},
  {0x21d3, "arrowdbldown"},
  {0x21d0, "arrowdblleft"},
  {0x21d2, "arrowdblright"},
  {0x21d1, "arrowdblup"},
  {0x2193, "arrowdown"},
  {0xf8e7, "arrowhorizex"},
  {0x2190, "arrowleft"},
  {0x2192, "arrowright"},
  {0x2191, "arrowup"},
  {0x2195, "arrowupdn"},
  {0x21a8, "arrowupdnbse"},
  {0xf8e6, "arrowvertex"},
  {0x005e, "asciicircum"},
  {0x007e, "asciitilde"},
  {0x002a, "asterisk"},
  {0x2217, "asteriskmath"},
  {0xf6e9, "asuperior"},
  {0x0040, "at"},
  {0x00e3, "atilde"},
  {0x0062, "b"},
  {0x005c, "backslash"},
  {0x007c, "bar"},
  {0x03b2, "beta"},
  {0x2588, "block"},
  {0xf8f4, "braceex"},
  {0x007b, "braceleft"},
  {0xf8f3, "braceleftbt"},
  {0xf8f2, "braceleftmid"},
  {0xf8f1, "bracelefttp"},
  {0x007d, "braceright"},
  {0xf8fe, "bracerightbt"},
  {0xf8fd, "bracerightmid"},
  {0xf8fc, "bracerighttp"},
  {0x005b, "bracketleft"},
  {0xf8f0, "bracketleftbt"},
  {0xf8ef, "bracketleftex"},
  {0xf8ee, "bracketlefttp"},
  {0x005d, "bracketright"},
  {0xf8fb, "bracketrightbt"},
  {0xf8fa, "bracketrightex"},
  {0xf8f9, "bracketrighttp"},
  {0x02d8, "breve"},
  {0x00a6, "brokenbar"},
  {0xf6ea, "bsuperior"},
  {0x2022, "bullet"},
  {0x0063, "c"},
  {0x0107, "cacute"},
  {0x02c7, "caron"},
  {0x21b5, "carriagereturn"},
  {0x010d, "ccaron"},
  {0x00e7, "ccedilla"},
  {0x0109, "ccircumflex"},
  {0x010b, "cdotaccent"},
  {0x00b8, "cedilla"},
  {0x00a2, "cent"},
  {0xf6df, "centinferior"},
  {0x00a2, "centoldstyle"},
  {0xf6e0, "centsuperior"},
  {0x03c7, "chi"},
  {0x25cb, "circle"},
  {0x2297, "circlemultiply"},
  {0x2295, "circleplus"},
  {0x02c6, "circumflex"},
  {0x2663, "club"},
  {0x003a, "colon"},
  {0x20a1, "colonmonetary"},
  {0x002c, "comma"},
  {0xf6c3, "commaaccent"},
  {0xf6e1, "commainferior"},
  {0xf6e2, "commasuperior"},
  {0x2245, "congruent"},
  {0x00a9, "copyright"},
  {0x00a9, "copyrightsans"},
  {0x00a9, "copyrightserif"},
  {0x00a4, "currency"},
  {0xf6d1, "cyrBreve"},
  {0xf6d2, "cyrFlex"},
  {0xf6d4, "cyrbreve"},
  {0xf6d5, "cyrflex"},
  {0x0064, "d"},
  {0x2020, "dagger"},
  {0x2021, "daggerdbl"},
  {0xf6d3, "dblGrave"},
  {0xf6d6, "dblgrave"},
  {0x010f, "dcaron"},
  {0x0111, "dcroat"},
  {0x00b0, "degree"},
  {0x03b4, "delta"},
  {0x2666, "diamond"},
  {0x00a8, "dieresis"},
  {0xf6d7, "dieresisacute"},
  {0xf6d8, "dieresisgrave"},
  {0x0385, "dieresistonos"},
  {0x00f7, "divide"},
  {0x2593, "dkshade"},
  {0x2584, "dnblock"},
  {0x0024, "dollar"},
  {0xf6e3, "dollarinferior"},
  {0x0024, "dollaroldstyle"},
  {0xf6e4, "dollarsuperior"},
  {0x20ab, "dong"},
  {0x02d9, "dotaccent"},
  {0x0323, "dotbelowcomb"},
  {0x0131, "dotlessi"},
  {0xf6be, "dotlessj"},
  {0x22c5, "dotmath"},
  {0xf6eb, "dsuperior"},
  {0x0065, "e"},
  {0x00e9, "eacute"},
  {0x0115, "ebreve"},
  {0x011b, "ecaron"},
  {0x00ea, "ecircumflex"},
  {0x00eb, "edieresis"},
  {0x0117, "edotaccent"},
  {0x00e8, "egrave"},
  {0x0038, "eight"},
  {0x2088, "eightinferior"},
  {0x0038, "eightoldstyle"},
  {0x2078, "eightsuperior"},
  {0x2208, "element"},
  {0x2026, "ellipsis"},
  {0x0113, "emacron"},
  {0x2014, "emdash"},
  {0x2205, "emptyset"},
  {0x2013, "endash"},
  {0x014b, "eng"},
  {0x0119, "eogonek"},
  {0x03b5, "epsilon"},
  {0x03ad, "epsilontonos"},
  {0x003d, "equal"},
  {0x2261, "equivalence"},
  {0x212e, "estimated"},
  {0xf6ec, "esuperior"},
  {0x03b7, "eta"},
  {0x03ae, "etatonos"},
  {0x00f0, "eth"},
  {0x0021, "exclam"},
  {0x203c, "exclamdbl"},
  {0x00a1, "exclamdown"},
  {0x00a1, "exclamdownsmall"},
  {0x0021, "exclamleft"},
  {0x0021, "exclamsmall"},
  {0x2203, "existential"},
  {0x0066, "f"},
  {0xfb00, "ff"},
  {0xfb03, "ffi"},
  {0xfb04, "ffl"},
  {0xfb01, "fi"},
  {0xfb00, "f_f"},
  {0xfb03, "f_f_i"},
  {0xfb04, "f_f_l"},
  {0xfb01, "f_i"},
  {0x2640, "female"},
  {0x2012, "figuredash"},
  {0x25a0, "filledbox"},
  {0x25ac, "filledrect"},
  {0x0035, "five"},
  {0x215d, "fiveeighths"},
  {0x2085, "fiveinferior"},
  {0x0035, "fiveoldstyle"},
  {0x2075, "fivesuperior"},
  {0xfb02, "fl"},
  {0xfb02, "f_l"},
  {0x0192, "florin"},
  {0x0034, "four"},
  {0x2084, "fourinferior"},
  {0x0034, "fouroldstyle"},
  {0x2074, "foursuperior"},
  {0x2044, "fraction"},
  {0x20a3, "franc"},
  {0x0067, "g"},
  {0x03b3, "gamma"},
  {0x011f, "gbreve"},
  {0x01e7, "gcaron"},
  {0x011d, "gcircumflex"},
  {0x0123, "gcommaaccent"},
  {0x0121, "gdotaccent"},
  {0x00df, "germandbls"},
  {0x2207, "gradient"},
  {0x0060, "grave"},
  {0x0300, "gravecomb"},
  {0x003e, "greater"},
  {0x2265, "greaterequal"},
  {0x00ab, "guillemotleft"},
  {0x00bb, "guillemotright"},
  {0x2039, "guilsinglleft"},
  {0x203a, "guilsinglright"},
  {0x0068, "h"},
  {0x0127, "hbar"},
  {0x0125, "hcircumflex"},
  {0x2665, "heart"},
  {0x0309, "hookabovecomb"},
  {0x2302, "house"},
  {0x02dd, "hungarumlaut"},
  {0x002d, "hyphen"},
  {0xf6e5, "hypheninferior"},
  {0xf6e6, "hyphensuperior"},
  {0x0069, "i"},
  {0x00ed, "iacute"},
  {0x012d, "ibreve"},
  {0x00ee, "icircumflex"},
  {0x00ef, "idieresis"},
  {0x00ec, "igrave"},
  {0x0133, "ij"},
  {0x012b, "imacron"},
  {0x221e, "infinity"},
  {0x222b, "integral"},
  {0x2321, "integralbt"},
  {0xf8f5, "integralex"},
  {0x2320, "integraltp"},
  {0x2229, "intersection"},
  {0x25d8, "invbullet"},
  {0x25d9, "invcircle"},
  {0x263b, "invsmileface"},
  {0x012f, "iogonek"},
  {0x03b9, "iota"},
  {0x03ca, "iotadieresis"},
  {0x0390, "iotadieresistonos"},
  {0x03af, "iotatonos"},
  {0xf6ed, "isuperior"},
  {0x0129, "itilde"},
  {0x006a, "j"},
  {0x0135, "jcircumflex"},
  {0x006b, "k"},
  {0x03ba, "kappa"},
  {0x0137, "kcommaaccent"},
  {0x0138, "kgreenlandic"},
  {0x006c, "l"},
  {0x013a, "lacute"},
  {0x03bb, "lambda"},
  {0x013e, "lcaron"},
  {0x013c, "lcommaaccent"},
  {0x0140, "ldot"},
  {0x003c, "less"},
  {0x2264, "lessequal"},
  {0x258c, "lfblock"},
  {0x20a4, "lira"},
  {0xf6c0, "ll"},
  {0x2227, "logicaland"},
  {0x00ac, "logicalnot"},
  {0x2228, "logicalor"},
  {0x017f, "longs"},
  {0x25ca, "lozenge"},
  {0x0142, "lslash"},
  {0xf6ee, "lsuperior"},
  {0x2591, "ltshade"},
  {0x006d, "m"},
  {0x00af, "macron"},
  {0x2642, "male"},
  {0x2212, "minus"},
  {0x2032, "minute"},
  {0xf6ef, "msuperior"},
  {0x00b5, "mu"},
  {0x00d7, "multiply"},
  {0x266a, "musicalnote"},
  {0x266b, "musicalnotedbl"},
  {0x006e, "n"},
  {0x0144, "nacute"},
  {0x0149, "napostrophe"},
  {0x00a0, "nbspace"},
  {0x0148, "ncaron"},
  {0x0146, "ncommaaccent"},
  {0x0039, "nine"},
  {0x2089, "nineinferior"},
  {0x0039, "nineoldstyle"},
  {0x2079, "ninesuperior"},
  {0x00a0, "nonbreakingspace"},
  {0x2209, "notelement"},
  {0x2260, "notequal"},
  {0x2284, "notsubset"},
  {0x207f, "nsuperior"},
  {0x00f1, "ntilde"},
  {0x03bd, "nu"},
  {0x0023, "numbersign"},
  {0x006f, "o"},
  {0x00f3, "oacute"},
  {0x014f, "obreve"},
  {0x00f4, "ocircumflex"},
  {0x00f6, "odieresis"},
  {0x0153, "oe"},
  {0x02db, "ogonek"},
  {0x00f2, "ograve"},
  {0x01a1, "ohorn"},
  {0x0151, "ohungarumlaut"},
  {0x014d, "omacron"},
  {0x03c9, "omega"},
  {0x03d6, "omega1"},
  {0x03ce, "omegatonos"},
  {0x03bf, "omicron"},
  {0x03cc, "omicrontonos"},
  {0x0031, "one"},
  {0x2024, "onedotenleader"},
  {0x215b, "oneeighth"},
  {0xf6dc, "onefitted"},
  {0x00bd, "onehalf"},
  {0x2081, "oneinferior"},
  {0x0031, "oneoldstyle"},
  {0x00bc, "onequarter"},
  {0x00b9, "onesuperior"},
  {0x2153, "onethird"},
  {0x25e6, "openbullet"},
  {0x00aa, "ordfeminine"},
  {0x00ba, "ordmasculine"},
  {0x221f, "orthogonal"},
  {0x00f8, "oslash"},
  {0x01ff, "oslashacute"},
  {0xf6f0, "osuperior"},
  {0x00f5, "otilde"},
  {0x0070, "p"},
  {0x00b6, "paragraph"},
  {0x0028, "parenleft"},
  {0xf8ed, "parenleftbt"},
  {0xf8ec, "parenleftex"},
  {0x208d, "parenleftinferior"},
  {0x207d, "parenleftsuperior"},
  {0xf8eb, "parenlefttp"},
  {0x0029, "parenright"},
  {0xf8f8, "parenrightbt"},
  {0xf8f7, "parenrightex"},
  {0x208e, "parenrightinferior"},
  {0x207e, "parenrightsuperior"},
  {0xf8f6, "parenrighttp"},
  {0x2202, "partialdiff"},
  {0x0025, "percent"},
  {0x002e, "period"},
  {0x00b7, "periodcentered"},
  {0xf6e7, "periodinferior"},
  {0xf6e8, "periodsuperior"},
  {0x22a5, "perpendicular"},
  {0x2030, "perthousand"},
  {0x20a7, "peseta"},
  {0x03c6, "phi"},
  {0x03d5, "phi1"},
  {0x03c0, "pi"},
  {0x002b, "plus"},
  {0x00b1, "plusminus"},
  {0x211e, "prescription"},
  {0x220f, "product"},
  {0x2282, "propersubset"},
  {0x2283, "propersuperset"},
  {0x221d, "proportional"},
  {0x03c8, "psi"},
  {0x0071, "q"},
  {0x003f, "question"},
  {0x00bf, "questiondown"},
  {0x00bf, "questiondownsmall"},
  {0x003f, "questionsmall"},
  {0x0022, "quotedbl"},
  {0x201e, "quotedblbase"},
  {0x201c, "quotedblleft"},
  {0x201d, "quotedblright"},
  {0x2018, "quoteleft"},
  {0x201b, "quotereversed"},
  {0x2019, "quoteright"},
  {0x201a, "quotesinglbase"},
  {0x0027, "quotesingle"},
  {0x0072, "r"},
  {0x0155, "racute"},
  {0x221a, "radical"},
  {0xf8e5, "radicalex"},
  {0x0159, "rcaron"},
  {0x0157, "rcommaaccent"},
  {0x2286, "reflexsubset"},
  {0x2287, "reflexsuperset"},
  {0x00ae, "registered"},
  {0x00ae, "registersans"},
  {0x00ae, "registerserif"},
  {0x2310, "revlogicalnot"},
  {0x03c1, "rho"},
  {0x02da, "ring"},
  {0xf6f1, "rsuperior"},
  {0x2590, "rtblock"},
  {0xf6dd, "rupiah"},
  {0x0073, "s"},
  {0x015b, "sacute"},
  {0x0161, "scaron"},
  {0x015f, "scedilla"},
  {0x015d, "scircumflex"},
  {0x0219, "scommaaccent"},
  {0x2033, "second"},
  {0x00a7, "section"},
  {0x003b, "semicolon"},
  {0x0037, "seven"},
  {0x215e, "seveneighths"},
  {0x2087, "seveninferior"},
  {0x0037, "sevenoldstyle"},
  {0x2077, "sevensuperior"},
  {0x2592, "shade"},
  {0x03c3, "sigma"},
  {0x03c2, "sigma1"},
  {0x223c, "similar"},
  {0x0036, "six"},
  {0x2086, "sixinferior"},
  {0x0036, "sixoldstyle"},
  {0x2076, "sixsuperior"},
  {0x002f, "slash"},
  {0x263a, "smileface"},
  {0x0020, "space"},
  {0x2660, "spade"},
  {0xf6f2, "ssuperior"},
  {0x00a3, "sterling"},
  {0x220b, "suchthat"},
  {0x2211, "summation"},
  {0x263c, "sun"},
  {0x0074, "t"},
  {0x03c4, "tau"},
  {0x0167, "tbar"},
  {0x0165, "tcaron"},
  {0x0163, "tcommaaccent"},
  {0x2234, "therefore"},
  {0x03b8, "theta"},
  {0x03d1, "theta1"},
  {0x00fe, "thorn"},
  {0x0033, "three"},
  {0x215c, "threeeighths"},
  {0x2083, "threeinferior"},
  {0x0033, "threeoldstyle"},
  {0x00be, "threequarters"},
  {0xf6de, "threequartersemdash"},
  {0x00b3, "threesuperior"},
  {0x02dc, "tilde"},
  {0x0303, "tildecomb"},
  {0x0384, "tonos"},
  {0x2122, "trademark"},
  {0x2122, "trademarksans"},
  {0x2122, "trademarkserif"},
  {0x25bc, "triagdn"},
  {0x25c4, "triaglf"},
  {0x25ba, "triagrt"},
  {0x25b2, "triagup"},
  {0xf6f3, "tsuperior"},
  {0x0032, "two"},
  {0x2025, "twodotenleader"},
  {0x2082, "twoinferior"},
  {0x0032, "twooldstyle"},
  {0x00b2, "twosuperior"},
  {0x2154, "twothirds"},
  {0x0075, "u"},
  {0x00fa, "uacute"},
  {0x016d, "ubreve"},
  {0x00fb, "ucircumflex"},
  {0x00fc, "udieresis"},
  {0x00f9, "ugrave"},
  {0x01b0, "uhorn"},
  {0x0171, "uhungarumlaut"},
  {0x016b, "umacron"},
  {0x005f, "underscore"},
  {0x2017, "underscoredbl"},
  {0x222a, "union"},
  {0x2200, "universal"},
  {0x0173, "uogonek"},
  {0x2580, "upblock"},
  {0x03c5, "upsilon"},
  {0x03cb, "upsilondieresis"},
  {0x03b0, "upsilondieresistonos"},
  {0x03cd, "upsilontonos"},
  {0x016f, "uring"},
  {0x0169, "utilde"},
  {0x0076, "v"},
  {0x0077, "w"},
  {0x1e83, "wacute"},
  {0x0175, "wcircumflex"},
  {0x1e85, "wdieresis"},
  {0x2118, "weierstrass"},
  {0x1e81, "wgrave"},
  {0x0078, "x"},
  {0x03be, "xi"},
  {0x0079, "y"},
  {0x00fd, "yacute"},
  {0x0177, "ycircumflex"},
  {0x00ff, "ydieresis"},
  {0x00a5, "yen"},
  {0x1ef3, "ygrave"},
  {0x007a, "z"},
  {0x017a, "zacute"},
  {0x017e, "zcaron"},
  {0x017c, "zdotaccent"},
  {0x0030, "zero"},
  {0x2080, "zeroinferior"},
  {0x0030, "zerooldstyle"},
  {0x2070, "zerosuperior"},
  {0x03b6, "zeta"},
  {0x007b, "{"},
  {0x007c, "|"},
  {0x007d, "}"},
  {0x007e, "~"},
  { 0, NULL }
};

static struct {
    pdf_utf16be u;
    const char *name;
} UnicodeToNameTab[] = {    
    {0x0000, ".notdef"},
    {0x0020, "space"},
    {0x0021, "exclam"},
    {0x0022, "quotedbl"},
    {0x0023, "numbersign"},
    {0x0024, "dollar"},
    {0x0025, "percent"},
    {0x0026, "ampersand"},
    {0x0027, "quotesingle"},
    {0x0028, "parenleft"},
    {0x0029, "parenright"},
    {0x002A, "asterisk"},
    {0x002B, "plus"},
    {0x002C, "comma"},
    {0x002D, "hyphen"},
    {0x002E, "period"},
    {0x002F, "slash"},
    {0x0030, "zero"},
    {0x0031, "one"},
    {0x0032, "two"},
    {0x0033, "three"},
    {0x0034, "four"},
    {0x0035, "five"},
    {0x0036, "six"},
    {0x0037, "seven"},
    {0x0038, "eight"},
    {0x0039, "nine"},
    {0x003A, "colon"},
    {0x003B, "semicolon"},
    {0x003C, "less"},
    {0x003D, "equal"},
    {0x003E, "greater"},
    {0x003F, "question"},
    {0x0040, "at"},
    {0x0041, "A"},
    {0x0042, "B"},
    {0x0043, "C"},
    {0x0044, "D"},
    {0x0045, "E"},
    {0x0046, "F"},
    {0x0047, "G"},
    {0x0048, "H"},
    {0x0049, "I"},
    {0x004A, "J"},
    {0x004B, "K"},
    {0x004C, "L"},
    {0x004D, "M"},
    {0x004E, "N"},
    {0x004F, "O"},
    {0x0050, "P"},
    {0x0051, "Q"},
    {0x0052, "R"},
    {0x0053, "S"},
    {0x0054, "T"},
    {0x0055, "U"},
    {0x0056, "V"},
    {0x0057, "W"},
    {0x0058, "X"},
    {0x0059, "Y"},
    {0x005A, "Z"},
    {0x005B, "bracketleft"},
    {0x005C, "backslash"},
    {0x005D, "bracketright"},
    {0x005E, "asciicircum"},
    {0x005F, "underscore"},
    {0x0060, "grave"},
    {0x0061, "a"},
    {0x0062, "b"},
    {0x0063, "c"},
    {0x0064, "d"},
    {0x0065, "e"},
    {0x0066, "f"},
    {0x0067, "g"},
    {0x0068, "h"},
    {0x0069, "i"},
    {0x006A, "j"},
    {0x006B, "k"},
    {0x006C, "l"},
    {0x006D, "m"},
    {0x006E, "n"},
    {0x006F, "o"},
    {0x0070, "p"},
    {0x0071, "q"},
    {0x0072, "r"},
    {0x0073, "s"},
    {0x0074, "t"},
    {0x0075, "u"},
    {0x0076, "v"},
    {0x0077, "w"},
    {0x0078, "x"},
    {0x0079, "y"},
    {0x007A, "z"},
    {0x007B, "braceleft"},
    {0x007C, "bar"},
    {0x007D, "braceright"},
    {0x007E, "asciitilde"},
    {0x00A0, "space"},
    {0x00A1, "exclamdown"},
    {0x00A2, "cent"},
    {0x00A3, "sterling"},
    {0x00A4, "currency"},
    {0x00A5, "yen"},
    {0x00A6, "brokenbar"},
    {0x00A7, "section"},
    {0x00A8, "dieresis"},
    {0x00A9, "copyright"},
    {0x00AA, "ordfeminine"},
    {0x00AB, "guillemotleft"},
    {0x00AC, "logicalnot"},
    {0x00AD, "hyphen"},
    {0x00AE, "registered"},
    {0x00AF, "macron"},
    {0x00B0, "degree"},
    {0x00B1, "plusminus"},
    {0x00B2, "twosuperior"},
    {0x00B3, "threesuperior"},
    {0x00B4, "acute"},
    {0x00B5, "mu"},
    {0x00B6, "paragraph"},
    {0x00B7, "periodcentered"},
    {0x00B8, "cedilla"},
    {0x00B9, "onesuperior"},
    {0x00BA, "ordmasculine"},
    {0x00BB, "guillemotright"},
    {0x00BC, "onequarter"},
    {0x00BD, "onehalf"},
    {0x00BE, "threequarters"},
    {0x00BF, "questiondown"},
    {0x00C0, "Agrave"},
    {0x00C1, "Aacute"},
    {0x00C2, "Acircumflex"},
    {0x00C3, "Atilde"},
    {0x00C4, "Adieresis"},
    {0x00C5, "Aring"},
    {0x00C6, "AE"},
    {0x00C7, "Ccedilla"},
    {0x00C8, "Egrave"},
    {0x00C9, "Eacute"},
    {0x00CA, "Ecircumflex"},
    {0x00CB, "Edieresis"},
    {0x00CC, "Igrave"},
    {0x00CD, "Iacute"},
    {0x00CE, "Icircumflex"},
    {0x00CF, "Idieresis"},
    {0x00D0, "Eth"},
    {0x00D1, "Ntilde"},
    {0x00D2, "Ograve"},
    {0x00D3, "Oacute"},
    {0x00D4, "Ocircumflex"},
    {0x00D5, "Otilde"},
    {0x00D6, "Odieresis"},
    {0x00D7, "multiply"},
    {0x00D8, "Oslash"},
    {0x00D9, "Ugrave"},
    {0x00DA, "Uacute"},
    {0x00DB, "Ucircumflex"},
    {0x00DC, "Udieresis"},
    {0x00DD, "Yacute"},
    {0x00DE, "Thorn"},
    {0x00DF, "germandbls"},
    {0x00E0, "agrave"},
    {0x00E1, "aacute"},
    {0x00E2, "acircumflex"},
    {0x00E3, "atilde"},
    {0x00E4, "adieresis"},
    {0x00E5, "aring"},
    {0x00E6, "ae"},
    {0x00E7, "ccedilla"},
    {0x00E8, "egrave"},
    {0x00E9, "eacute"},
    {0x00EA, "ecircumflex"},
    {0x00EB, "edieresis"},
    {0x00EC, "igrave"},
    {0x00ED, "iacute"},
    {0x00EE, "icircumflex"},
    {0x00EF, "idieresis"},
    {0x00F0, "eth"},
    {0x00F1, "ntilde"},
    {0x00F2, "ograve"},
    {0x00F3, "oacute"},
    {0x00F4, "ocircumflex"},
    {0x00F5, "otilde"},
    {0x00F6, "odieresis"},
    {0x00F7, "divide"},
    {0x00F8, "oslash"},
    {0x00F9, "ugrave"},
    {0x00FA, "uacute"},
    {0x00FB, "ucircumflex"},
    {0x00FC, "udieresis"},
    {0x00FD, "yacute"},
    {0x00FE, "thorn"},
    {0x00FF, "ydieresis"},
    {0x0100, "Amacron"},
    {0x0101, "amacron"},
    {0x0102, "Abreve"},
    {0x0103, "abreve"},
    {0x0104, "Aogonek"},
    {0x0105, "aogonek"},
    {0x0106, "Cacute"},
    {0x0107, "cacute"},
    {0x0108, "Ccircumflex"},
    {0x0109, "ccircumflex"},
    {0x010A, "Cdotaccent"},
    {0x010B, "cdotaccent"},
    {0x010C, "Ccaron"},
    {0x010D, "ccaron"},
    {0x010E, "Dcaron"},
    {0x010F, "dcaron"},
    {0x0110, "Dcroat"},
    {0x0111, "dcroat"},
    {0x0112, "Emacron"},
    {0x0113, "emacron"},
    {0x0114, "Ebreve"},
    {0x0115, "ebreve"},
    {0x0116, "Edotaccent"},
    {0x0117, "edotaccent"},
    {0x0118, "Eogonek"},
    {0x0119, "eogonek"},
    {0x011A, "Ecaron"},
    {0x011B, "ecaron"},
    {0x011C, "Gcircumflex"},
    {0x011D, "gcircumflex"},
    {0x011E, "Gbreve"},
    {0x011F, "gbreve"},
    {0x0120, "Gdotaccent"},
    {0x0121, "gdotaccent"},
    {0x0122, "Gcommaaccent"},
    {0x0123, "gcommaaccent"},
    {0x0124, "Hcircumflex"},
    {0x0125, "hcircumflex"},
    {0x0126, "Hbar"},
    {0x0127, "hbar"},
    {0x0128, "Itilde"},
    {0x0129, "itilde"},
    {0x012A, "Imacron"},
    {0x012B, "imacron"},
    {0x012C, "Ibreve"},
    {0x012D, "ibreve"},
    {0x012E, "Iogonek"},
    {0x012F, "iogonek"},
    {0x0130, "Idotaccent"},
    {0x0131, "dotlessi"},
    {0x0132, "IJ"},
    {0x0133, "ij"},
    {0x0134, "Jcircumflex"},
    {0x0135, "jcircumflex"},
    {0x0136, "Kcommaaccent"},
    {0x0137, "kcommaaccent"},
    {0x0138, "kgreenlandic"},
    {0x0139, "Lacute"},
    {0x013A, "lacute"},
    {0x013B, "Lcommaaccent"},
    {0x013C, "lcommaaccent"},
    {0x013D, "Lcaron"},
    {0x013E, "lcaron"},
    {0x013F, "Ldot"},
    {0x0140, "ldot"},
    {0x0141, "Lslash"},
    {0x0142, "lslash"},
    {0x0143, "Nacute"},
    {0x0144, "nacute"},
    {0x0145, "Ncommaaccent"},
    {0x0146, "ncommaaccent"},
    {0x0147, "Ncaron"},
    {0x0148, "ncaron"},
    {0x0149, "napostrophe"},
    {0x014A, "Eng"},
    {0x014B, "eng"},
    {0x014C, "Omacron"},
    {0x014D, "omacron"},
    {0x014E, "Obreve"},
    {0x014F, "obreve"},
    {0x0150, "Ohungarumlaut"},
    {0x0151, "ohungarumlaut"},
    {0x0152, "OE"},
    {0x0153, "oe"},
    {0x0154, "Racute"},
    {0x0155, "racute"},
    {0x0156, "Rcommaaccent"},
    {0x0157, "rcommaaccent"},
    {0x0158, "Rcaron"},
    {0x0159, "rcaron"},
    {0x015A, "Sacute"},
    {0x015B, "sacute"},
    {0x015C, "Scircumflex"},
    {0x015D, "scircumflex"},
    {0x015E, "Scedilla"},
    {0x015F, "scedilla"},
    {0x0160, "Scaron"},
    {0x0161, "scaron"},
    {0x0162, "Tcommaaccent"},
    {0x0163, "tcommaaccent"},
    {0x0164, "Tcaron"},
    {0x0165, "tcaron"},
    {0x0166, "Tbar"},
    {0x0167, "tbar"},
    {0x0168, "Utilde"},
    {0x0169, "utilde"},
    {0x016A, "Umacron"},
    {0x016B, "umacron"},
    {0x016C, "Ubreve"},
    {0x016D, "ubreve"},
    {0x016E, "Uring"},
    {0x016F, "uring"},
    {0x0170, "Uhungarumlaut"},
    {0x0171, "uhungarumlaut"},
    {0x0172, "Uogonek"},
    {0x0173, "uogonek"},
    {0x0174, "Wcircumflex"},
    {0x0175, "wcircumflex"},
    {0x0176, "Ycircumflex"},
    {0x0177, "ycircumflex"},
    {0x0178, "Ydieresis"},
    {0x0179, "Zacute"},
    {0x017A, "zacute"},
    {0x017B, "Zdotaccent"},
    {0x017C, "zdotaccent"},
    {0x017D, "Zcaron"},
    {0x017E, "zcaron"},
    {0x017F, "longs"},
    {0x0192, "florin"},
    {0x01A0, "Ohorn"},
    {0x01A1, "ohorn"},
    {0x01AF, "Uhorn"},
    {0x01B0, "uhorn"},
    {0x01E6, "Gcaron"},
    {0x01E7, "gcaron"},
    {0x01FA, "Aringacute"},
    {0x01FB, "aringacute"},
    {0x01FC, "AEacute"},
    {0x01FD, "aeacute"},
    {0x01FE, "Oslashacute"},
    {0x01FF, "oslashacute"},
    {0x0218, "Scommaaccent"},
    {0x0219, "scommaaccent"},
    {0x021A, "Tcommaaccent"},
    {0x021B, "tcommaaccent"},
    {0x02BC, "afii57929"},
    {0x02BD, "afii64937"},
    {0x02C6, "circumflex"},
    {0x02C7, "caron"},
    {0x02C9, "macron"},
    {0x02D8, "breve"},
    {0x02D9, "dotaccent"},
    {0x02DA, "ring"},
    {0x02DB, "ogonek"},
    {0x02DC, "tilde"},
    {0x02DD, "hungarumlaut"},
    {0x0300, "gravecomb"},
    {0x0301, "acutecomb"},
    {0x0303, "tildecomb"},
    {0x0309, "hookabovecomb"},
    {0x0323, "dotbelowcomb"},
    {0x0384, "tonos"},
    {0x0385, "dieresistonos"},
    {0x0386, "Alphatonos"},
    {0x0387, "anoteleia"},
    {0x0388, "Epsilontonos"},
    {0x0389, "Etatonos"},
    {0x038A, "Iotatonos"},
    {0x038C, "Omicrontonos"},
    {0x038E, "Upsilontonos"},
    {0x038F, "Omegatonos"},
    {0x0390, "iotadieresistonos"},
    {0x0391, "Alpha"},
    {0x0392, "Beta"},
    {0x0393, "Gamma"},
    {0x0394, "Delta"},
    {0x0395, "Epsilon"},
    {0x0396, "Zeta"},
    {0x0397, "Eta"},
    {0x0398, "Theta"},
    {0x0399, "Iota"},
    {0x039A, "Kappa"},
    {0x039B, "Lambda"},
    {0x039C, "Mu"},
    {0x039D, "Nu"},
    {0x039E, "Xi"},
    {0x039F, "Omicron"},
    {0x03A0, "Pi"},
    {0x03A1, "Rho"},
    {0x03A3, "Sigma"},
    {0x03A4, "Tau"},
    {0x03A5, "Upsilon"},
    {0x03A6, "Phi"},
    {0x03A7, "Chi"},
    {0x03A8, "Psi"},
    {0x03A9, "Omega"},
    {0x03AA, "Iotadieresis"},
    {0x03AB, "Upsilondieresis"},
    {0x03AC, "alphatonos"},
    {0x03AD, "epsilontonos"},
    {0x03AE, "etatonos"},
    {0x03AF, "iotatonos"},
    {0x03B0, "upsilondieresistonos"},
    {0x03B1, "alpha"},
    {0x03B2, "beta"},
    {0x03B3, "gamma"},
    {0x03B4, "delta"},
    {0x03B5, "epsilon"},
    {0x03B6, "zeta"},
    {0x03B7, "eta"},
    {0x03B8, "theta"},
    {0x03B9, "iota"},
    {0x03BA, "kappa"},
    {0x03BB, "lambda"},
    {0x03BC, "mu"},
    {0x03BD, "nu"},
    {0x03BE, "xi"},
    {0x03BF, "omicron"},
    {0x03C0, "pi"},
    {0x03C1, "rho"},
    {0x03C2, "sigma1"},
    {0x03C3, "sigma"},
    {0x03C4, "tau"},
    {0x03C5, "upsilon"},
    {0x03C6, "phi"},
    {0x03C7, "chi"},
    {0x03C8, "psi"},
    {0x03C9, "omega"},
    {0x03CA, "iotadieresis"},
    {0x03CB, "upsilondieresis"},
    {0x03CC, "omicrontonos"},
    {0x03CD, "upsilontonos"},
    {0x03CE, "omegatonos"},
    {0x03D1, "theta1"},
    {0x03D2, "Upsilon1"},
    {0x03D5, "phi1"},
    {0x03D6, "omega1"},
    {0x0401, "afii10023"},
    {0x0402, "afii10051"},
    {0x0403, "afii10052"},
    {0x0404, "afii10053"},
    {0x0405, "afii10054"},
    {0x0406, "afii10055"},
    {0x0407, "afii10056"},
    {0x0408, "afii10057"},
    {0x0409, "afii10058"},
    {0x040A, "afii10059"},
    {0x040B, "afii10060"},
    {0x040C, "afii10061"},
    {0x040E, "afii10062"},
    {0x040F, "afii10145"},
    {0x0410, "afii10017"},
    {0x0411, "afii10018"},
    {0x0412, "afii10019"},
    {0x0413, "afii10020"},
    {0x0414, "afii10021"},
    {0x0415, "afii10022"},
    {0x0416, "afii10024"},
    {0x0417, "afii10025"},
    {0x0418, "afii10026"},
    {0x0419, "afii10027"},
    {0x041A, "afii10028"},
    {0x041B, "afii10029"},
    {0x041C, "afii10030"},
    {0x041D, "afii10031"},
    {0x041E, "afii10032"},
    {0x041F, "afii10033"},
    {0x0420, "afii10034"},
    {0x0421, "afii10035"},
    {0x0422, "afii10036"},
    {0x0423, "afii10037"},
    {0x0424, "afii10038"},
    {0x0425, "afii10039"},
    {0x0426, "afii10040"},
    {0x0427, "afii10041"},
    {0x0428, "afii10042"},
    {0x0429, "afii10043"},
    {0x042A, "afii10044"},
    {0x042B, "afii10045"},
    {0x042C, "afii10046"},
    {0x042D, "afii10047"},
    {0x042E, "afii10048"},
    {0x042F, "afii10049"},
    {0x0430, "afii10065"},
    {0x0431, "afii10066"},
    {0x0432, "afii10067"},
    {0x0433, "afii10068"},
    {0x0434, "afii10069"},
    {0x0435, "afii10070"},
    {0x0436, "afii10072"},
    {0x0437, "afii10073"},
    {0x0438, "afii10074"},
    {0x0439, "afii10075"},
    {0x043A, "afii10076"},
    {0x043B, "afii10077"},
    {0x043C, "afii10078"},
    {0x043D, "afii10079"},
    {0x043E, "afii10080"},
    {0x043F, "afii10081"},
    {0x0440, "afii10082"},
    {0x0441, "afii10083"},
    {0x0442, "afii10084"},
    {0x0443, "afii10085"},
    {0x0444, "afii10086"},
    {0x0445, "afii10087"},
    {0x0446, "afii10088"},
    {0x0447, "afii10089"},
    {0x0448, "afii10090"},
    {0x0449, "afii10091"},
    {0x044A, "afii10092"},
    {0x044B, "afii10093"},
    {0x044C, "afii10094"},
    {0x044D, "afii10095"},
    {0x044E, "afii10096"},
    {0x044F, "afii10097"},
    {0x0451, "afii10071"},
    {0x0452, "afii10099"},
    {0x0453, "afii10100"},
    {0x0454, "afii10101"},
    {0x0455, "afii10102"},
    {0x0456, "afii10103"},
    {0x0457, "afii10104"},
    {0x0458, "afii10105"},
    {0x0459, "afii10106"},
    {0x045A, "afii10107"},
    {0x045B, "afii10108"},
    {0x045C, "afii10109"},
    {0x045E, "afii10110"},
    {0x045F, "afii10193"},
    {0x0462, "afii10146"},
    {0x0463, "afii10194"},
    {0x0472, "afii10147"},
    {0x0473, "afii10195"},
    {0x0474, "afii10148"},
    {0x0475, "afii10196"},
    {0x0490, "afii10050"},
    {0x0491, "afii10098"},
    {0x04D9, "afii10846"},
    {0x05B0, "afii57799"},
    {0x05B1, "afii57801"},
    {0x05B2, "afii57800"},
    {0x05B3, "afii57802"},
    {0x05B4, "afii57793"},
    {0x05B5, "afii57794"},
    {0x05B6, "afii57795"},
    {0x05B7, "afii57798"},
    {0x05B8, "afii57797"},
    {0x05B9, "afii57806"},
    {0x05BB, "afii57796"},
    {0x05BC, "afii57807"},
    {0x05BD, "afii57839"},
    {0x05BE, "afii57645"},
    {0x05BF, "afii57841"},
    {0x05C0, "afii57842"},
    {0x05C1, "afii57804"},
    {0x05C2, "afii57803"},
    {0x05C3, "afii57658"},
    {0x05D0, "afii57664"},
    {0x05D1, "afii57665"},
    {0x05D2, "afii57666"},
    {0x05D3, "afii57667"},
    {0x05D4, "afii57668"},
    {0x05D5, "afii57669"},
    {0x05D6, "afii57670"},
    {0x05D7, "afii57671"},
    {0x05D8, "afii57672"},
    {0x05D9, "afii57673"},
    {0x05DA, "afii57674"},
    {0x05DB, "afii57675"},
    {0x05DC, "afii57676"},
    {0x05DD, "afii57677"},
    {0x05DE, "afii57678"},
    {0x05DF, "afii57679"},
    {0x05E0, "afii57680"},
    {0x05E1, "afii57681"},
    {0x05E2, "afii57682"},
    {0x05E3, "afii57683"},
    {0x05E4, "afii57684"},
    {0x05E5, "afii57685"},
    {0x05E6, "afii57686"},
    {0x05E7, "afii57687"},
    {0x05E8, "afii57688"},
    {0x05E9, "afii57689"},
    {0x05EA, "afii57690"},
    {0x05F0, "afii57716"},
    {0x05F1, "afii57717"},
    {0x05F2, "afii57718"},
    {0x060C, "afii57388"},
    {0x061B, "afii57403"},
    {0x061F, "afii57407"},
    {0x0621, "afii57409"},
    {0x0622, "afii57410"},
    {0x0623, "afii57411"},
    {0x0624, "afii57412"},
    {0x0625, "afii57413"},
    {0x0626, "afii57414"},
    {0x0627, "afii57415"},
    {0x0628, "afii57416"},
    {0x0629, "afii57417"},
    {0x062A, "afii57418"},
    {0x062B, "afii57419"},
    {0x062C, "afii57420"},
    {0x062D, "afii57421"},
    {0x062E, "afii57422"},
    {0x062F, "afii57423"},
    {0x0630, "afii57424"},
    {0x0631, "afii57425"},
    {0x0632, "afii57426"},
    {0x0633, "afii57427"},
    {0x0634, "afii57428"},
    {0x0635, "afii57429"},
    {0x0636, "afii57430"},
    {0x0637, "afii57431"},
    {0x0638, "afii57432"},
    {0x0639, "afii57433"},
    {0x063A, "afii57434"},
    {0x0640, "afii57440"},
    {0x0641, "afii57441"},
    {0x0642, "afii57442"},
    {0x0643, "afii57443"},
    {0x0644, "afii57444"},
    {0x0645, "afii57445"},
    {0x0646, "afii57446"},
    {0x0647, "afii57470"},
    {0x0648, "afii57448"},
    {0x0649, "afii57449"},
    {0x064A, "afii57450"},
    {0x064B, "afii57451"},
    {0x064C, "afii57452"},
    {0x064D, "afii57453"},
    {0x064E, "afii57454"},
    {0x064F, "afii57455"},
    {0x0650, "afii57456"},
    {0x0651, "afii57457"},
    {0x0652, "afii57458"},
    {0x0660, "afii57392"},
    {0x0661, "afii57393"},
    {0x0662, "afii57394"},
    {0x0663, "afii57395"},
    {0x0664, "afii57396"},
    {0x0665, "afii57397"},
    {0x0666, "afii57398"},
    {0x0667, "afii57399"},
    {0x0668, "afii57400"},
    {0x0669, "afii57401"},
    {0x066A, "afii57381"},
    {0x066D, "afii63167"},
    {0x0679, "afii57511"},
    {0x067E, "afii57506"},
    {0x0686, "afii57507"},
    {0x0688, "afii57512"},
    {0x0691, "afii57513"},
    {0x0698, "afii57508"},
    {0x06A4, "afii57505"},
    {0x06AF, "afii57509"},
    {0x06BA, "afii57514"},
    {0x06D2, "afii57519"},
    {0x06D5, "afii57534"},
    {0x1E80, "Wgrave"},
    {0x1E81, "wgrave"},
    {0x1E82, "Wacute"},
    {0x1E83, "wacute"},
    {0x1E84, "Wdieresis"},
    {0x1E85, "wdieresis"},
    {0x1EF2, "Ygrave"},
    {0x1EF3, "ygrave"},
    {0x200C, "afii61664"},
    {0x200D, "afii301"},
    {0x200E, "afii299"},
    {0x200F, "afii300"},
    {0x2012, "figuredash"},
    {0x2013, "endash"},
    {0x2014, "emdash"},
    {0x2015, "afii00208"},
    {0x2017, "underscoredbl"},
    {0x2018, "quoteleft"},
    {0x2019, "quoteright"},
    {0x201A, "quotesinglbase"},
    {0x201B, "quotereversed"},
    {0x201C, "quotedblleft"},
    {0x201D, "quotedblright"},
    {0x201E, "quotedblbase"},
    {0x2020, "dagger"},
    {0x2021, "daggerdbl"},
    {0x2022, "bullet"},
    {0x2024, "onedotenleader"},
    {0x2025, "twodotenleader"},
    {0x2026, "ellipsis"},
    {0x202C, "afii61573"},
    {0x202D, "afii61574"},
    {0x202E, "afii61575"},
    {0x2030, "perthousand"},
    {0x2032, "minute"},
    {0x2033, "second"},
    {0x2039, "guilsinglleft"},
    {0x203A, "guilsinglright"},
    {0x203C, "exclamdbl"},
    {0x2044, "fraction"},
    {0x2070, "zerosuperior"},
    {0x2074, "foursuperior"},
    {0x2075, "fivesuperior"},
    {0x2076, "sixsuperior"},
    {0x2077, "sevensuperior"},
    {0x2078, "eightsuperior"},
    {0x2079, "ninesuperior"},
    {0x207D, "parenleftsuperior"},
    {0x207E, "parenrightsuperior"},
    {0x207F, "nsuperior"},
    {0x2080, "zeroinferior"},
    {0x2081, "oneinferior"},
    {0x2082, "twoinferior"},
    {0x2083, "threeinferior"},
    {0x2084, "fourinferior"},
    {0x2085, "fiveinferior"},
    {0x2086, "sixinferior"},
    {0x2087, "seveninferior"},
    {0x2088, "eightinferior"},
    {0x2089, "nineinferior"},
    {0x208D, "parenleftinferior"},
    {0x208E, "parenrightinferior"},
    {0x20A1, "colonmonetary"},
    {0x20A3, "franc"},
    {0x20A4, "lira"},
    {0x20A7, "peseta"},
    {0x20AA, "afii57636"},
    {0x20AB, "dong"},
    {0x20AC, "Euro"},
    {0x2105, "afii61248"},
    {0x2111, "Ifraktur"},
    {0x2113, "afii61289"},
    {0x2116, "afii61352"},
    {0x2118, "weierstrass"},
    {0x211C, "Rfraktur"},
    {0x211E, "prescription"},
    {0x2122, "trademark"},
    {0x2126, "Omega"},
    {0x212E, "estimated"},
    {0x2135, "aleph"},
    {0x2153, "onethird"},
    {0x2154, "twothirds"},
    {0x215B, "oneeighth"},
    {0x215C, "threeeighths"},
    {0x215D, "fiveeighths"},
    {0x215E, "seveneighths"},
    {0x2190, "arrowleft"},
    {0x2191, "arrowup"},
    {0x2192, "arrowright"},
    {0x2193, "arrowdown"},
    {0x2194, "arrowboth"},
    {0x2195, "arrowupdn"},
    {0x21A8, "arrowupdnbse"},
    {0x21B5, "carriagereturn"},
    {0x21D0, "arrowdblleft"},
    {0x21D1, "arrowdblup"},
    {0x21D2, "arrowdblright"},
    {0x21D3, "arrowdbldown"},
    {0x21D4, "arrowdblboth"},
    {0x2200, "universal"},
    {0x2202, "partialdiff"},
    {0x2203, "existential"},
    {0x2205, "emptyset"},
    {0x2206, "Delta"},
    {0x2207, "gradient"},
    {0x2208, "element"},
    {0x2209, "notelement"},
    {0x220B, "suchthat"},
    {0x220F, "product"},
    {0x2211, "summation"},
    {0x2212, "minus"},
    {0x2215, "fraction"},
    {0x2217, "asteriskmath"},
    {0x2219, "periodcentered"},
    {0x221A, "radical"},
    {0x221D, "proportional"},
    {0x221E, "infinity"},
    {0x221F, "orthogonal"},
    {0x2220, "angle"},
    {0x2227, "logicaland"},
    {0x2228, "logicalor"},
    {0x2229, "intersection"},
    {0x222A, "union"},
    {0x222B, "integral"},
    {0x2234, "therefore"},
    {0x223C, "similar"},
    {0x2245, "congruent"},
    {0x2248, "approxequal"},
    {0x2260, "notequal"},
    {0x2261, "equivalence"},
    {0x2264, "lessequal"},
    {0x2265, "greaterequal"},
    {0x2282, "propersubset"},
    {0x2283, "propersuperset"},
    {0x2284, "notsubset"},
    {0x2286, "reflexsubset"},
    {0x2287, "reflexsuperset"},
    {0x2295, "circleplus"},
    {0x2297, "circlemultiply"},
    {0x22A5, "perpendicular"},
    {0x22C5, "dotmath"},
    {0x2302, "house"},
    {0x2310, "revlogicalnot"},
    {0x2320, "integraltp"},
    {0x2321, "integralbt"},
    {0x2329, "angleleft"},
    {0x232A, "angleright"},
    {0x2500, "SF100000"},
    {0x2502, "SF110000"},
    {0x250C, "SF010000"},
    {0x2510, "SF030000"},
    {0x2514, "SF020000"},
    {0x2518, "SF040000"},
    {0x251C, "SF080000"},
    {0x2524, "SF090000"},
    {0x252C, "SF060000"},
    {0x2534, "SF070000"},
    {0x253C, "SF050000"},
    {0x2550, "SF430000"},
    {0x2551, "SF240000"},
    {0x2552, "SF510000"},
    {0x2553, "SF520000"},
    {0x2554, "SF390000"},
    {0x2555, "SF220000"},
    {0x2556, "SF210000"},
    {0x2557, "SF250000"},
    {0x2558, "SF500000"},
    {0x2559, "SF490000"},
    {0x255A, "SF380000"},
    {0x255B, "SF280000"},
    {0x255C, "SF270000"},
    {0x255D, "SF260000"},
    {0x255E, "SF360000"},
    {0x255F, "SF370000"},
    {0x2560, "SF420000"},
    {0x2561, "SF190000"},
    {0x2562, "SF200000"},
    {0x2563, "SF230000"},
    {0x2564, "SF470000"},
    {0x2565, "SF480000"},
    {0x2566, "SF410000"},
    {0x2567, "SF450000"},
    {0x2568, "SF460000"},
    {0x2569, "SF400000"},
    {0x256A, "SF540000"},
    {0x256B, "SF530000"},
    {0x256C, "SF440000"},
    {0x2580, "upblock"},
    {0x2584, "dnblock"},
    {0x2588, "block"},
    {0x258C, "lfblock"},
    {0x2590, "rtblock"},
    {0x2591, "ltshade"},
    {0x2592, "shade"},
    {0x2593, "dkshade"},
    {0x25A0, "filledbox"},
    {0x25A1, "H22073"},
    {0x25AA, "H18543"},
    {0x25AB, "H18551"},
    {0x25AC, "filledrect"},
    {0x25B2, "triagup"},
    {0x25BA, "triagrt"},
    {0x25BC, "triagdn"},
    {0x25C4, "triaglf"},
    {0x25CA, "lozenge"},
    {0x25CB, "circle"},
    {0x25CF, "H18533"},
    {0x25D8, "invbullet"},
    {0x25D9, "invcircle"},
    {0x25E6, "openbullet"},
    {0x263A, "smileface"},
    {0x263B, "invsmileface"},
    {0x263C, "sun"},
    {0x2640, "female"},
    {0x2642, "male"},
    {0x2660, "spade"},
    {0x2663, "club"},
    {0x2665, "heart"},
    {0x2666, "diamond"},
    {0x266A, "musicalnote"},
    {0x266B, "musicalnotedbl"},
    {0xF6BE, "dotlessj"},
    {0xF6BF, "LL"},
    {0xF6C0, "ll"},
    {0xF6C1, "Scedilla"},
    {0xF6C2, "scedilla"},
    {0xF6C3, "commaaccent"},
    {0xF6C4, "afii10063"},
    {0xF6C5, "afii10064"},
    {0xF6C6, "afii10192"},
    {0xF6C7, "afii10831"},
    {0xF6C8, "afii10832"},
    {0xF6C9, "Acute"},
    {0xF6CA, "Caron"},
    {0xF6CB, "Dieresis"},
    {0xF6CC, "DieresisAcute"},
    {0xF6CD, "DieresisGrave"},
    {0xF6CE, "Grave"},
    {0xF6CF, "Hungarumlaut"},
    {0xF6D0, "Macron"},
    {0xF6D1, "cyrBreve"},
    {0xF6D2, "cyrFlex"},
    {0xF6D3, "dblGrave"},
    {0xF6D4, "cyrbreve"},
    {0xF6D5, "cyrflex"},
    {0xF6D6, "dblgrave"},
    {0xF6D7, "dieresisacute"},
    {0xF6D8, "dieresisgrave"},
    {0xF6D9, "copyrightserif"},
    {0xF6DA, "registerserif"},
    {0xF6DB, "trademarkserif"},
    {0xF6DC, "onefitted"},
    {0xF6DD, "rupiah"},
    {0xF6DE, "threequartersemdash"},
    {0xF6DF, "centinferior"},
    {0xF6E0, "centsuperior"},
    {0xF6E1, "commainferior"},
    {0xF6E2, "commasuperior"},
    {0xF6E3, "dollarinferior"},
    {0xF6E4, "dollarsuperior"},
    {0xF6E5, "hypheninferior"},
    {0xF6E6, "hyphensuperior"},
    {0xF6E7, "periodinferior"},
    {0xF6E8, "periodsuperior"},
    {0xF6E9, "asuperior"},
    {0xF6EA, "bsuperior"},
    {0xF6EB, "dsuperior"},
    {0xF6EC, "esuperior"},
    {0xF6ED, "isuperior"},
    {0xF6EE, "lsuperior"},
    {0xF6EF, "msuperior"},
    {0xF6F0, "osuperior"},
    {0xF6F1, "rsuperior"},
    {0xF6F2, "ssuperior"},
    {0xF6F3, "tsuperior"},
    {0xF6F4, "Brevesmall"},
    {0xF6F5, "Caronsmall"},
    {0xF6F6, "Circumflexsmall"},
    {0xF6F7, "Dotaccentsmall"},
    {0xF6F8, "Hungarumlautsmall"},
    {0xF6F9, "Lslashsmall"},
    {0xF6FA, "OEsmall"},
    {0xF6FB, "Ogoneksmall"},
    {0xF6FC, "Ringsmall"},
    {0xF6FD, "Scaronsmall"},
    {0xF6FE, "Tildesmall"},
    {0xF6FF, "Zcaronsmall"},
    {0xF721, "exclamsmall"},
    {0xF724, "dollaroldstyle"},
    {0xF726, "ampersandsmall"},
    {0xF730, "zerooldstyle"},
    {0xF731, "oneoldstyle"},
    {0xF732, "twooldstyle"},
    {0xF733, "threeoldstyle"},
    {0xF734, "fouroldstyle"},
    {0xF735, "fiveoldstyle"},
    {0xF736, "sixoldstyle"},
    {0xF737, "sevenoldstyle"},
    {0xF738, "eightoldstyle"},
    {0xF739, "nineoldstyle"},
    {0xF73F, "questionsmall"},
    {0xF760, "Gravesmall"},
    {0xF761, "Asmall"},
    {0xF762, "Bsmall"},
    {0xF763, "Csmall"},
    {0xF764, "Dsmall"},
    {0xF765, "Esmall"},
    {0xF766, "Fsmall"},
    {0xF767, "Gsmall"},
    {0xF768, "Hsmall"},
    {0xF769, "Ismall"},
    {0xF76A, "Jsmall"},
    {0xF76B, "Ksmall"},
    {0xF76C, "Lsmall"},
    {0xF76D, "Msmall"},
    {0xF76E, "Nsmall"},
    {0xF76F, "Osmall"},
    {0xF770, "Psmall"},
    {0xF771, "Qsmall"},
    {0xF772, "Rsmall"},
    {0xF773, "Ssmall"},
    {0xF774, "Tsmall"},
    {0xF775, "Usmall"},
    {0xF776, "Vsmall"},
    {0xF777, "Wsmall"},
    {0xF778, "Xsmall"},
    {0xF779, "Ysmall"},
    {0xF77A, "Zsmall"},
    {0xF7A1, "exclamdownsmall"},
    {0xF7A2, "centoldstyle"},
    {0xF7A8, "Dieresissmall"},
    {0xF7AF, "Macronsmall"},
    {0xF7B4, "Acutesmall"},
    {0xF7B8, "Cedillasmall"},
    {0xF7BF, "questiondownsmall"},
    {0xF7E0, "Agravesmall"},
    {0xF7E1, "Aacutesmall"},
    {0xF7E2, "Acircumflexsmall"},
    {0xF7E3, "Atildesmall"},
    {0xF7E4, "Adieresissmall"},
    {0xF7E5, "Aringsmall"},
    {0xF7E6, "AEsmall"},
    {0xF7E7, "Ccedillasmall"},
    {0xF7E8, "Egravesmall"},
    {0xF7E9, "Eacutesmall"},
    {0xF7EA, "Ecircumflexsmall"},
    {0xF7EB, "Edieresissmall"},
    {0xF7EC, "Igravesmall"},
    {0xF7ED, "Iacutesmall"},
    {0xF7EE, "Icircumflexsmall"},
    {0xF7EF, "Idieresissmall"},
    {0xF7F0, "Ethsmall"},
    {0xF7F1, "Ntildesmall"},
    {0xF7F2, "Ogravesmall"},
    {0xF7F3, "Oacutesmall"},
    {0xF7F4, "Ocircumflexsmall"},
    {0xF7F5, "Otildesmall"},
    {0xF7F6, "Odieresissmall"},
    {0xF7F8, "Oslashsmall"},
    {0xF7F9, "Ugravesmall"},
    {0xF7FA, "Uacutesmall"},
    {0xF7FB, "Ucircumflexsmall"},
    {0xF7FC, "Udieresissmall"},
    {0xF7FD, "Yacutesmall"},
    {0xF7FE, "Thornsmall"},
    {0xF7FF, "Ydieresissmall"},
    {0xF8E5, "radicalex"},
    {0xF8E6, "arrowvertex"},
    {0xF8E7, "arrowhorizex"},
    {0xF8E8, "registersans"},
    {0xF8E9, "copyrightsans"},
    {0xF8EA, "trademarksans"},
    {0xF8EB, "parenlefttp"},
    {0xF8EC, "parenleftex"},
    {0xF8ED, "parenleftbt"},
    {0xF8EE, "bracketlefttp"},
    {0xF8EF, "bracketleftex"},
    {0xF8F0, "bracketleftbt"},
    {0xF8F1, "bracelefttp"},
    {0xF8F2, "braceleftmid"},
    {0xF8F3, "braceleftbt"},
    {0xF8F4, "braceex"},
    {0xF8F5, "integralex"},
    {0xF8F6, "parenrighttp"},
    {0xF8F7, "parenrightex"},
    {0xF8F8, "parenrightbt"},
    {0xF8F9, "bracketrighttp"},
    {0xF8FA, "bracketrightex"},
    {0xF8FB, "bracketrightbt"},
    {0xF8FC, "bracerighttp"},
    {0xF8FD, "bracerightmid"},
    {0xF8FE, "bracerightbt"},
    {0xFB00, "ff"},
    {0xFB01, "fi"},
    {0xFB02, "fl"},
    {0xFB03, "ffi"},
    {0xFB04, "ffl"},
    {0xFB1F, "afii57705"},
    {0xFB2A, "afii57694"},
    {0xFB2B, "afii57695"},
    {0xFB35, "afii57723"},
    {0xFB4B, "afii57700"},
    {0xFFFF, NULL}
};

PdfEncodingDifference::PdfEncodingDifference()
{
}

PdfEncodingDifference::PdfEncodingDifference( const PdfEncodingDifference & rhs )
{
    this->operator=( rhs );
}

const PdfEncodingDifference & PdfEncodingDifference::operator=( const PdfEncodingDifference & rhs )
{
    m_vecDifferences = rhs.m_vecDifferences;

    return *this;
}

void PdfEncodingDifference::AddDifference( int nCode )
{
#ifdef PODOFO_IS_LITTLE_ENDIAN
    pdf_utf16be inCodePoint = ((nCode & 0xff00) >> 8) | ((nCode & 0xff) << 8);
#else
    pdf_utf16be inCodePoint = nCode;
#endif // PODOFO_IS_LITTLE_ENDIAN

    this->AddDifference( nCode, PdfDifferenceEncoding::UnicodeIDToName( inCodePoint ) );
}

void PdfEncodingDifference::AddDifference( int nCode, const PdfName & rName )
{
    if( nCode > 255 || nCode < 0 ) 
    {
        PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
    }

    TDifference dif;
    dif.nCode        = nCode;
    dif.name         = rName;
    dif.unicodeValue = 0;

    std::pair<TIVecDifferences,TCIVecDifferences> it = 
        std::equal_range( m_vecDifferences.begin(), m_vecDifferences.end(), dif, DifferenceComparatorPredicate() );

    if( it.first != it.second )
    {
        // replace existing object
        *(it.first) = dif;
    }
    else
    {
        m_vecDifferences.insert( it.first, dif );
    }
}


bool PdfEncodingDifference::Contains( int nCode, PdfName & rName, pdf_utf16be & rValue ) const
{
    TDifference dif;
    dif.nCode = nCode;

    std::pair<TIVecDifferences,TIVecDifferences> it = 
        std::equal_range( const_cast<PdfEncodingDifference*>(this)->m_vecDifferences.begin(), 
                          const_cast<PdfEncodingDifference*>(this)->m_vecDifferences.end(), 
                          dif, DifferenceComparatorPredicate() );

    if( it.first != it.second )
    {
        rName  = (*(it.first)).name;
        if( !(*(it.first)).unicodeValue )
            // Field is not yet initialized,
            // initialize it now, so that we only
            // compute the value if it is needed.
            (*(it.first)).unicodeValue = PdfDifferenceEncoding::NameToUnicodeID( rName );

        rValue = (*(it.first)).unicodeValue;
        
        return true;
    }

    return false;
}

void PdfEncodingDifference::ToArray( PdfArray & rArray )
{
    pdf_int64 nLastCode = -2;

    rArray.Clear();

    TCIVecDifferences it = m_vecDifferences.begin();
    while( it != m_vecDifferences.end() )
    {
        if( (*it).nCode != nLastCode + 1 ) 
        {
            nLastCode = (*it).nCode;

            rArray.push_back( nLastCode );
            rArray.push_back( (*it).name );
        }
        else
        {
            ++nLastCode;
            rArray.push_back( (*it).name );
        }

        ++it;
    }
}

// -----------------------------------------------------
// PdfDifferenceEncoding
// -----------------------------------------------------
PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfDocument* pParent, bool bAutoDelete )
    : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), 
      m_differences( rDifference ),
      m_bAutoDelete( bAutoDelete ), 
      m_baseEncoding( eBaseEncoding_Font )
{
    Init();
}

PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfVecObjects* pParent, bool bAutoDelete )
    : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), 
      m_differences( rDifference ),
      m_bAutoDelete( bAutoDelete ), 
      m_baseEncoding( eBaseEncoding_Font )
{
    Init();
}

PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, 
                                              PdfDocument* pParent, bool bAutoDelete )
    : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), 
      m_differences( rDifference ),
      m_bAutoDelete( bAutoDelete ), 
      m_baseEncoding( eBaseEncoding )
{
    Init();
}

PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, 
                                              PdfVecObjects* pParent, bool bAutoDelete )
    : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), 
      m_differences( rDifference ),
      m_bAutoDelete( bAutoDelete ), 
      m_baseEncoding( eBaseEncoding )
{
    Init();
}

PdfDifferenceEncoding::PdfDifferenceEncoding( PdfObject* pObject, bool bAutoDelete )
    : PdfEncoding( 0x00, 0xff ), PdfElement( NULL, pObject ),
      m_bAutoDelete( bAutoDelete )
{
    CreateID();
    
    m_baseEncoding = eBaseEncoding_WinAnsi;

    if( this->GetObject()->GetDictionary().HasKey( PdfName("BaseEncoding") ) )
    {
        const PdfName & rBase = this->GetObject()->GetDictionary().GetKey( PdfName("BaseEncoding") )->GetName();
        
        if( rBase == PdfName("WinAnsiEncoding") )
            m_baseEncoding = eBaseEncoding_WinAnsi;
        else if( rBase == PdfName("MacRomanEncoding") )
            m_baseEncoding = eBaseEncoding_MacRoman;
        else if( rBase == PdfName("MacExpertEncoding") )
            m_baseEncoding = eBaseEncoding_MacExpert;
    }    

    // Read the differences key
    if( this->GetObject()->GetDictionary().HasKey( PdfName("Differences") ) )
    {
        const PdfArray & rDifferences = this->GetObject()->GetIndirectKey( PdfName("Differences") )->GetArray();
        PdfArray::const_iterator it = rDifferences.begin();

        long long curCode = -1;

        while( it != rDifferences.end() ) 
        {
            if( (*it).IsNumber() ) 
                curCode = (*it).GetNumber();
            else if( (*it).IsName() ) 
            {
                m_differences.AddDifference( static_cast<int>(curCode), (*it).GetName() );
                ++curCode;
            }
            
            ++it;
        }
    }
}

void PdfDifferenceEncoding::CreateID() 
{
    std::ostringstream oss;
    oss << "/DifferencesEncoding" << this->GetObject()->Reference().ObjectNumber() 
        << "_" << this->GetObject()->Reference().GenerationNumber();

    m_id = PdfName( oss.str() );    
}

void PdfDifferenceEncoding::Init()
{
    CreateID();

    switch( m_baseEncoding ) 
    {
        case eBaseEncoding_WinAnsi:
            this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"),
                                               PdfName("WinAnsiEncoding") );
            break;

        case eBaseEncoding_MacRoman:
            this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"),
                                               PdfName("MacRomanEncoding") );
            break;
        case eBaseEncoding_MacExpert:
            this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"),
                                               PdfName("MacExpertEncoding") );
            break;

        case eBaseEncoding_Font:
        default:
            break;
    }

    if( m_differences.GetCount() ) 
    {
        PdfArray differences;
        m_differences.ToArray( differences );
    
        this->GetObject()->GetDictionary().AddKey( PdfName("Differences"), differences );
    }                      
}

void PdfDifferenceEncoding::AddToDictionary( PdfDictionary & rDictionary ) const
{
    rDictionary.AddKey( PdfName("Encoding"), this->GetObject()->Reference() );
}

pdf_utf16be PdfDifferenceEncoding::GetCharCode( int nIndex ) const
{
    if( nIndex < this->GetFirstChar() ||
        nIndex > this->GetLastChar() )
    {
        PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
    }

    PdfName     name;
    pdf_utf16be value;
    if( m_differences.Contains( nIndex, name, value ) )
    {
	return value;
    }
    else
    {
	const PdfEncoding* pEncoding = this->GetBaseEncoding();
	return pEncoding->GetCharCode( nIndex ); 
    }
}

pdf_utf16be PdfDifferenceEncoding::NameToUnicodeID( const PdfName & rName )
{
    const char* pszName = rName.GetName().c_str();

    for( int i = 0; nameToUnicodeTab[i].name; ++i) 
    {
        if ( strcmp( nameToUnicodeTab[i].name, pszName ) == 0 )
#ifdef PODOFO_IS_LITTLE_ENDIAN
            return ((nameToUnicodeTab[i].u & 0xff00) >> 8) | ((nameToUnicodeTab[i].u & 0xff) << 8);
#else
            return nameToUnicodeTab[i].u;
#endif // PODOFO_IS_LITTLE_ENDIAN
    }

    // if we get here, then we might be looking up an undefined codepoint
    // so try looking for our special format..
    if( strncmp( "uni", pszName, 3 ) == 0 ) 
    {
        pszName += 3; // remove "uni"
        size_t length = strlen( pszName );

        // force base16 IF it's 4 characters line
        pdf_utf16be val = static_cast<pdf_utf16be>(strtol( pszName, NULL, (length == 4 ? 16 : 10) ));

#ifdef PODOFO_IS_LITTLE_ENDIAN
        return val = ((val & 0xff00) >> 8) | ((val & 0xff) << 8);
#else
        return val;
#endif // PODOFO_IS_LITTLE_ENDIAN
    }

    return 0;
}

PdfName PdfDifferenceEncoding::UnicodeIDToName( pdf_utf16be inCodePoint )
{
#ifdef PODOFO_IS_LITTLE_ENDIAN
    inCodePoint = ((inCodePoint & 0xff00) >> 8) | ((inCodePoint & 0xff) << 8);
#endif // PODOFO_IS_LITTLE_ENDIAN

    int i;
	for( i = 0; UnicodeToNameTab[i].name; ++i) 
    {
        if ( UnicodeToNameTab[i].u == inCodePoint ) 
            return PdfName( UnicodeToNameTab[i].name );
    }

    // if we can't find in the canonical list, look in the complete list
    for ( i = 0; nameToUnicodeTab[i].name; ++i) 
    {
        if ( nameToUnicodeTab[i].u == inCodePoint )
            return PdfName( UnicodeToNameTab[i].name );
    }

    // if we get here, then we are looking up an undefined codepoint
    // so we'll just give it SOME name..
    const int BUFFER_LEN = 8;
    char buffer[BUFFER_LEN];
    snprintf( buffer, BUFFER_LEN, "uni%04x", inCodePoint );

    return PdfName( buffer );
    //return PdfName(".notdef");
}

PdfString PdfDifferenceEncoding::ConvertToUnicode( const PdfString & rEncodedString, 
                                                   const PdfFont* pFont ) const
{
    const PdfEncoding* pEncoding = GetBaseEncoding();
    
    PdfString str  = pEncoding->ConvertToUnicode( rEncodedString, pFont );
    pdf_long      lLen = str.GetCharacterLength();

    pdf_utf16be* pszUtf16 = static_cast<pdf_utf16be*>(malloc(sizeof(pdf_utf16be)*lLen));
    if( !pszUtf16 )
    {
        PODOFO_RAISE_ERROR( ePdfError_OutOfMemory );
    }

    memcpy( pszUtf16, str.GetUnicode(), lLen * sizeof(pdf_utf16be) );

    for( pdf_long i=0;i<lLen;i++ ) 
    {
        pdf_utf16be val = pszUtf16[i];
#ifdef PODOFO_IS_LITTLE_ENDIAN
        val = ((val & 0xff00) >> 8) | ((val & 0xff) << 8);
#endif // PODOFO_IS_LITTLE_ENDIAN

        PdfName     name;
        pdf_utf16be value;
        if( m_differences.Contains( static_cast<int>(val), name, value ) )
            pszUtf16[i] = value;
    }

    PdfString ret( pszUtf16, lLen );
    free( pszUtf16 );

    return ret;
}

PdfRefCountedBuffer PdfDifferenceEncoding::ConvertToEncoding( const PdfString & rString, 
                                                    const PdfFont* pFont ) const
{
    const PdfEncoding* pEncoding = GetBaseEncoding();

    pdf_utf16be* pszUtf16 = NULL;
    pdf_long         lLen     = 0;

    if( rString.IsUnicode() )
    {
        lLen = rString.GetCharacterLength();
        pszUtf16 = static_cast<pdf_utf16be*>(malloc(sizeof(pdf_utf16be)*lLen));
        if( !pszUtf16 )
        {
            PODOFO_RAISE_ERROR( ePdfError_OutOfMemory );
        }
        memcpy( pszUtf16, rString.GetUnicode(), lLen * sizeof(pdf_utf16be) );
    }
    else
    {
        // Only do a copy if we really have to
        PdfString str = rString.ToUnicode();
        lLen = str.GetCharacterLength();
        pszUtf16 = static_cast<pdf_utf16be*>(malloc(sizeof(pdf_utf16be)*lLen));
        if( !pszUtf16 )
        {
            PODOFO_RAISE_ERROR( ePdfError_OutOfMemory );
        }
        memcpy( pszUtf16, str.GetUnicode(), lLen * sizeof(pdf_utf16be) );
    }

    for( int i=0;i<lLen;i++ ) 
    {
        pdf_utf16be val = pszUtf16[i];
#ifdef PODOFO_IS_LITTLE_ENDIAN
        val = ((val & 0xff00) >> 8) | ((val & 0xff) << 8);
#endif // PODOFO_IS_LITTLE_ENDIAN

        PdfName     name;
        pdf_utf16be value;
        if( m_differences.Contains( static_cast<int>(val), name, value ) )
            pszUtf16[i] = value;
    }

    PdfString ret( pszUtf16, lLen );
    free( pszUtf16 );

    return pEncoding->ConvertToEncoding( ret, pFont );
}

const PdfEncoding* PdfDifferenceEncoding::GetBaseEncoding() const
{
    const PdfEncoding* pEncoding = NULL;

    switch( m_baseEncoding ) 
    {
        case eBaseEncoding_WinAnsi:
            pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance();
            break;

        case eBaseEncoding_MacRoman:
            pEncoding = PdfEncodingFactory::GlobalMacRomanEncodingInstance();
            break;

        case eBaseEncoding_MacExpert:
        case eBaseEncoding_Font:
        default:
            break;
    }

    if( !pEncoding ) 
    {
        PODOFO_RAISE_ERROR( ePdfError_InvalidHandle );
    }

    return pEncoding;
}

}; /* PoDoFo */
